/*
 * Copyright (c) 2015 Messcat. All rights reserved.
 */
package cc.messcat.common.dao;

import cc.messcat.common.model.Pager;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Repository;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;

@Repository("baseDao")
public class BaseDaoImpl<T> extends BaseHibernateDaoUtil implements BaseDao<T> {

    public Class<T> getGenericClass() {
        try {
            return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        } catch (Exception e) {
            return (Class<T>) Object.class;
        }
    }

    @Override
    public <K> K get(Class<K> clazz, long id) {
        return (K) getCurrentSession().get(clazz, id);
    }

    @Override
    public final T get(final long id) {
        return get(getGenericClass(), id);
    }

    @Override
    public <K> List<K> getAll(Class<K> clazz) {
        return getCurrentSession().createCriteria(clazz).list();
    }

    @Override
    public final List<T> getAll() {
        return getAll(getGenericClass());
    }

    @Override
    public final void save(final Object entity) {
        getCurrentSession().saveOrUpdate(entity);
    }

    @Override
    public final Long save1(final Object entity) {
        return (Long) getCurrentSession().save(entity);
    }

    @Override
    public <K> K update(K entity) {
        getCurrentSession().update(entity);
        return entity;
    }

    @Override
    public final void delete(final Object entity) {
        getCurrentSession().delete(entity);
    }

    @Override
    public <K> void deleteById(Class<K> clazz, long entityId) {
        final K entity = get(clazz, entityId);
        delete(entity);
    }

    @Override
    public final void deleteById(final long entityId) {
        deleteById(getGenericClass(), entityId);
    }

    @Override
    public <K> List<K> findByExample(K entity) {
        Example example = Example.create(entity)
                .excludeZeroes()        //排除值为0的属性
                .excludeProperty("serialVersionUID");  //排除 属性
        return getCurrentSession().createCriteria(entity.getClass()).add(example).list();
    }

    /**
     * hql查询数量
     *
     * @param hql
     * @param conditions
     * @return
     */
    private int queryCount(final String hql, final Object... conditions) {
        Query query = getCurrentSession().createQuery(hql);
        if (conditions != null) {
            for (int i = 0; i < conditions.length; i++) {
                query.setParameter(i, conditions[i]);
            }
        }
        Long count = (Long) query.uniqueResult();
        return count.intValue();
    }

    private int queryCount(final String hql, final List conditions) {
        Query query = getCurrentSession().createQuery(hql);
        if (conditions != null) {
            for (int i = 0; i < conditions.size(); i++) {
                query.setParameter(i, conditions.get(i));
            }
        }
        Long count = (Long) query.uniqueResult();
        return count.intValue();
    }

    private int queryCount(final String hql, final Map conditions) {
        Query query = getCurrentSession().createQuery(hql);
        if (conditions != null && conditions.size() > 0) {
            query.setProperties(conditions);
        }
        Long count = (Long) query.uniqueResult();
        return count.intValue();
    }

    /**
     * hql分页查询
     */
    public Pager<T> getPagerByHql(int pageNo, int pageSize, String hql, Object... attrs) {
        List<T> resultList = this.findPageObjects(hql, pageNo, pageSize, attrs);
        int rowCount = this.queryCount("select count(*) " + hql, attrs);
        return new Pager<T>(pageSize, pageNo, rowCount, resultList);
    }

    /**
     * hql分页查询
     *
     * @return
     */
    public List<T> findPageObjects(String hql, int pageNo, int pageSize, final Object... conditions) {
        int pageStart = (pageNo - 1) * pageSize;
        Query query = getCurrentSession().createQuery(hql);
        if (null != conditions) {
            for (int i = 0; i < conditions.length; i++) {
                query.setParameter(i, conditions[i]);
            }
        }
        query.setFirstResult(pageStart);
        query.setMaxResults(pageSize);
        return query.list();
    }


    /**
     * hql分页查询
     */
    @Override
    public Pager<T> getPagerByHql(String hql, String count, Integer pageNo, Integer pageSize, Map condition) {
        Query query = getCurrentSession().createQuery(hql);
        if (null != condition) {
            query.setProperties(condition);
        }

        pageNo = pageNo == null || pageNo < 1 ? 1 : pageNo;
        pageSize = pageSize == null || pageSize < 1 ? 12 : pageSize;
        int pageStart = (pageNo - 1) * pageSize;

        query.setFirstResult(pageStart);
        query.setMaxResults(pageSize);
        List list = query.list();

        query = getCurrentSession().createQuery(count);
        if (null != condition) {
            query.setProperties(condition);
        }
        Long rows = (Long) query.uniqueResult();

        return new Pager<T>(pageSize, pageNo, rows.intValue(), list);
    }


    @Override
    public <K> K getByState(Class<K> clazz, final long id) {
        return (K) getCurrentSession().createCriteria(clazz).add(Restrictions.eq("id", id))
                .add(Restrictions.eq("state", "1")).uniqueResult();
    }

    @Override
    public T getByState(final long id) {
        return getByState(getGenericClass(), id);
    }

    @Override
    public <K> List<K> getAllByState(Class<K> clazz) {
        return getCurrentSession().createCriteria(clazz).add(Restrictions.eq("state", "1")).list();
    }

    @Override
    public List<T> getAllByState() {
        return getAllByState(getGenericClass());
    }

    /**
     * 执行更新语句
     *
     * @param sql
     */
    public void modifyByHql(String sql) {
        getCurrentSession().createQuery(sql).executeUpdate();
    }

    /**
     * hql分页查询
     */
    public Pager getPagerByHql(Integer pageNo, Integer pageSize, String hql, Map attrs) {
        pageNo = ((pageNo == null || pageNo < 1) ? 1 : pageNo);
        pageSize = ((pageSize == null || pageSize < 1) ? 8 : pageSize);
        List resultList = this.findPageObjects(hql, pageNo, pageSize, attrs);
        int rowCount = this.queryCount("select count(*) " + hql, attrs);
        return new Pager(pageSize, pageNo, rowCount, resultList);
    }

    /**
     * hql分页查询
     *
     * @return
     */
    public List findPageObjects(String hql, int pageNo, int pageSize, final Map conditions) {
        int pageStart = (pageNo - 1) * pageSize;
        Query query = getCurrentSession().createQuery(hql);
        if (null != conditions) {
            query.setProperties(conditions);
        }
        query.setFirstResult(pageStart);
        query.setMaxResults(pageSize);
        return query.list();
    }

    /**
     * 查询全部根据条件
     */
    public List queryList(String hql, Map map) {
        Query query = getCurrentSession().createQuery(hql);
        if (null != map) {
            query.setProperties(map);
        }
        return query.list();
    }

    /**
     * 查询
     */
    public List find(String hql) {
        Query query = getCurrentSession().createQuery(hql);
        return query.list();
    }

    /**
     * 执行sql语句，返回Map结果集
     */
    public List<Map<String, Object>> findToMapBySql(String sql, Object... args) {
        SQLQuery sqlQuery = getCurrentSession().createSQLQuery(sql);
        if (args != null) {
            for (int i = 0, j = args.length; i < j; i++) {
                sqlQuery.setParameter(i, args[i]);
            }
        }
        return sqlQuery.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
    }
}